package com.ev.framework.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ev.common.service.ReceiveService;
import com.ev.common.service.impl.ReceiveServiceCodeImpl;
import com.ev.framework.utils.RSAUtils;
import com.ev.framework.utils.StringUtils;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 注册码拦截
 */
public class AppServiceTimeFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(XssFilter.class);
    public List<String> excludes = new ArrayList<>();

    @Override
    public void init(FilterConfig filterConfig) {
        if (logger.isDebugEnabled()) {
            logger.debug("app servcieTime filter init~~~~~~~~~~~~");
        }
        String temp = filterConfig.getInitParameter("excludes");
        if (temp != null) {
            String[] url = temp.split(",");
            excludes.addAll(Arrays.asList(url));
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (handleExcludeURL(request)) {
            filterChain.doFilter(servletRequest, servletResponse);
            return;
        }
        // 获取redis 中的服务码
//        StringRedisTemplate stringRedisTemplate = (StringRedisTemplate) WebApplicationContextUtils
//                .getRequiredWebApplicationContext(request.getServletContext()).getBean("stringRedisTemplate");
        // 获取服务码
        ReceiveService receiveServiceCodeImpl = (ReceiveServiceCodeImpl)WebApplicationContextUtils
                .getRequiredWebApplicationContext(request.getServletContext()).getBean("receiveServiceCodeImpl");
        String serviceCodeByRedis = receiveServiceCodeImpl.getServiceCodeByRedis();
//        Object obj = stringRedisTemplate.opsForValue().get("serviceCode");
        if (StringUtils.isNoneBlank(serviceCodeByRedis)) {
            String serviceCode = new String(Base64.getDecoder().decode(serviceCodeByRedis.getBytes()), StandardCharsets.UTF_8.name());
//			Map<String, Object> serviceCodeMap = JSONUtils.jsonToMap(serviceCode);
            JSONObject serviceCodeJSON = JSON.parseObject(serviceCode);
            // 验签
            boolean verify;
            try {
                String publicKey = serviceCodeJSON.getString("publicKey");
                String serviceLicense = serviceCodeJSON.getString("serviceLicense");
                String endTime = serviceCodeJSON.getString("serviceEndTime");
                verify = RSAUtils.verify(endTime.getBytes(), publicKey, serviceLicense);
                if (!verify) {
                    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                    response.setContentType("application/json; charset=UTF-8");
                    Map<String, Object> results = Maps.newHashMap();
                    results.put("code", 97);
                    results.put("msg", "用户服务码不正确，请获取正确的服务码！");
                    String rJson = JSON.toJSONString(results);
                    OutputStream out = response.getOutputStream();
                    out.write(rJson.getBytes(StandardCharsets.UTF_8.name()));
                    out.flush();
                    return;
                }
                Date now = new Date();
//    			Date endTime = DateFormatUtil.getDateByParttern(Date,"yyyy-MM-dd");
                Date serviceStartTime = serviceCodeJSON.getDate("serviceStartTime");
                Date serviceEndTime = serviceCodeJSON.getDate("serviceEndTime");
//				Date serviceStartTime = DateFormatUtil.getDateByParttern(startTime,DateFormatUtil.DATE_PATTERN_YMD);
//				Date serviceEndTime = DateFormatUtil.getDateByParttern(endTime,DateFormatUtil.DATE_PATTERN_YMD);

                if (serviceStartTime.after(now) || serviceEndTime.before(now)) {
                    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                    response.setContentType("application/json; charset=UTF-8");
                    Map<String, Object> results = Maps.newHashMap();
                    results.put("code", 96);
                    results.put("msg", "服务不在期限内");
                    String rJson = JSON.toJSONString(results);
                    OutputStream out = response.getOutputStream();
                    out.write(rJson.getBytes(StandardCharsets.UTF_8.name()));
                    out.flush();
                    return;
                }
                filterChain.doFilter(servletRequest, servletResponse);
                return;

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setContentType("application/json; charset=UTF-8");
        Map<String, Object> results = Maps.newHashMap();
        results.put("code", 95);
        results.put("msg", "没有生成服务码，请先获取服务码");
        String rJson = JSON.toJSONString(results);
        OutputStream out = response.getOutputStream();
        out.write(rJson.getBytes(StandardCharsets.UTF_8.name()));
        out.flush();
    }

    private boolean handleExcludeURL(HttpServletRequest request) {
        if (excludes == null || excludes.isEmpty()) {
            return false;
        }

        String url = request.getServletPath();
        for (String pattern : excludes) {
            Pattern p = Pattern.compile("^" + pattern);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }

        return false;
    }

    @Override
    public void destroy() {

    }
}
